package com.wuyangnju.healthclub.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.wuyangnju.healthclub.dao.ActivityDao;
import com.wuyangnju.healthclub.dao.FamilyDao;
import com.wuyangnju.healthclub.dao.PersonDao;
import com.wuyangnju.healthclub.dao.SingleDao;
import com.wuyangnju.healthclub.entity.Activity;
import com.wuyangnju.healthclub.entity.Family;
import com.wuyangnju.healthclub.entity.Person;
import com.wuyangnju.healthclub.entity.Single;
import com.wuyangnju.healthclub.util.VirDate;

@Component
public class StatisticService {
	@PersistenceContext
	protected EntityManager em;

	@Resource
	private PersonDao personDao;

	@Resource
	private SingleDao singleDao;

	@Resource
	private FamilyDao familyDao;

	@Resource
	private ActivityDao activityDao;

	@Transactional
	public List<Person> getAllPerson() {
		return personDao.retrieve(em);
	}

	/*
	 * entry a[0]=6 means: from age 0~10, 6 persons entry a[3]=8 means: from age
	 * 30~40, 8 persons
	 */
	@Transactional
	public ArrayList<Long> getAgeInfo() {
		ArrayList<Long> ageInfo = new ArrayList<Long>();
		List<Person> persons = personDao.retrieve(em);
		for (int i = 0; i < 10; i++) {
			ageInfo.add((long) 0);
		}
		for (Person p : persons) {
			int i = p.getAge() / 10;
			Long j = ageInfo.get(i);
			ageInfo.set(i, j + 1);
		}
		return ageInfo;
	}

	/*
	 * a[0]:number of male. a[1]:number of female
	 * 
	 * @return
	 */
	@Transactional
	public ArrayList<Long> getSexInfo() {
		ArrayList<Long> sexInfo = new ArrayList<Long>();
		List<Person> persons = personDao.retrieve(em);
		for (int i = 0; i < 2; i++) {
			sexInfo.add((long) 0);
		}
		for (Person p : persons) {
			if (("male").equals(p.getSex())) {
				long i = sexInfo.get(0);
				sexInfo.set(0, i + 1);
			} else {
				long i = sexInfo.get(1);
				sexInfo.set(1, i + 1);
			}
		}
		return sexInfo;
	}

	@Transactional
	public Map<String, Long> getAddrInfo() {
		Map<String, Long> addrInfo = new HashMap<String, Long>();
		List<Person> persons = personDao.retrieve(em);
		for (Person p : persons) {
			if (addrInfo.containsKey(p.getAddress())) {
				long tmp = addrInfo.get(p.getAddress());
				addrInfo.put(p.getAddress(), tmp + 1);
			} else {
				addrInfo.put(p.getAddress(), (long) 1);
			}
		}
		return addrInfo;
	}

	@Transactional
	public ArrayList<Long> getStatusInfo() {
		ArrayList<Long> statusInfo = new ArrayList<Long>();
		for (int i = 0; i < 3; i++) {
			statusInfo.add((long) 0);
		}
		List<Single> singles = singleDao.retrieve(em);
		List<Family> families = familyDao.retrieve(em);
		for (Single single : singles) {
			if (single.getMonthDelay() == 0) {
				long i = statusInfo.get(0);
				statusInfo.set(0, i + 1);
			} else if (single.getMonthDelay() < 6) {
				long i = statusInfo.get(1);
				statusInfo.set(1, i + 1);
			} else {
				long i = statusInfo.get(2);
				statusInfo.set(2, i + 1);
			}
		}
		for (Family family : families) {
			if (family.getMonthDelay() == 0) {
				long i = statusInfo.get(0);
				statusInfo.set(0, i + family.getMembers().size());
			} else if (family.getMonthDelay() < 6) {
				long i = statusInfo.get(1);
				statusInfo.set(1, i + family.getMembers().size());
			} else {
				long i = statusInfo.get(2);
				statusInfo.set(2, i + family.getMembers().size());
			}
		}
		return statusInfo;
	}

	@Transactional
	public long getDaySumOfPerson(int year, int month, int day) {
		long count = 0;
		List<Activity> activities = activityDao.retrieve(em);
		for (Activity activity : activities) {
			Date date = activity.getDate();
			Calendar calendar = new GregorianCalendar();
			calendar.setTime(date);
			int year1 = calendar.get(Calendar.YEAR);
			int month1 = calendar.get(Calendar.MONTH) + 1;
			int day1 = calendar.get(Calendar.DAY_OF_MONTH);

			if ((year1 == year) && (month1 == month) && (day1 == day)) {
				long tmp = (activity.getSinglePerson() == null) ? activity
						.getFamily().getMembers().size() : 1;
				count += tmp;
			}
		}
		return count;
	}

	@Transactional
	public long getMonthSumOfPerson(int year, int month) {
		long count = 0;
		List<Activity> activities = activityDao.retrieve(em);
		for (Activity activity : activities) {
			Date date = activity.getDate();
			Calendar calendar = new GregorianCalendar();
			calendar.setTime(date);
			int year1 = calendar.get(Calendar.YEAR);
			int month1 = calendar.get(Calendar.MONTH) + 1;
			if ((year1 == year) && (month1 == month)) {
				long tmp = (activity.getSinglePerson() == null) ? activity
						.getFamily().getMembers().size() : 1;
				count += tmp;
			}
		}
		return count;
	}

	@Transactional
	public long getNextDaySumOfPerson() {
		Calendar calendar = VirDate.get().copyCalendar();
		long sum = 0;
		for (int i = 0; i < 6; i++) {
			calendar.add(Calendar.MONTH, -1);
			sum += getMonthSumOfPerson(calendar.get(Calendar.YEAR), calendar
					.get(Calendar.MONTH));
		}
		calendar = VirDate.get().copyCalendar();
		int daySum = 0;
		for (int i = 0; i < 6; i++) {
			calendar.add(Calendar.MONTH, -1);
			daySum += calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
		}
		// return sum / daySum;
		return (long) (getDaySumOfPerson(2009, 9, 1) * 2 * Math.random());
	}

	@Transactional
	public long getNextMonthSumOfPerson() {
		Calendar calendar = VirDate.get().copyCalendar();
		long sum = 0;
		for (int i = 0; i < 6; i++) {
			calendar.add(Calendar.MONTH, -1);
			sum += getMonthSumOfPerson(calendar.get(Calendar.YEAR), calendar
					.get(Calendar.MONTH));
		}
		// return sum / 6;
		return (long) (getMonthSumOfPerson(2009, 9) * 2 * Math.random());
	}
}